#include "engine.hpp"
#include "graphics/gfxengine.hpp"
#include "graphics/openglgfxengine.hpp"

#include "system/timer.hpp"
#include "message/message.hpp"

bool Engine::Init()
{
    gfxEngine = new OpenGLGfxEngine();
    gfxEngine->Init();

    Message::attachEntityManager(&entityManager);
    Message::attachMessageManager(&messageManager);
    Message::attachGfxEngine(gfxEngine);

    return true;
}

void Engine::Load()
{
    entityManager.AddEntity(new Entity());
    entityManager.AddEntity(new Entity());

    SpriteManager* spriteManager = gfxEngine->spriteManager;

    // Lua ------------------
    state = lua_open();
    luaL_openlibs(state);
    luabind::open(state);

    luabind::module(state) [
        luabind::class_<SpriteManager>("SpriteManager")
            .def("AddSpriteDefinition", &SpriteManager::AddSpriteDefinition)
            .def("CreateSprite", &SpriteManager::CreateSprite)
            .def("GetSprite", &SpriteManager::GetSprite)
    ];

    luabind::module(state) [
        luabind::class_<Animation>("Animation")
            .def(luabind::constructor<>())
            .def("Add", (void(Animation::*)(int, int, int, int, unsigned int))&Animation::Add)
    ];

    luabind::module(state) [
        luabind::class_<Sprite>("Sprite")
            .def_readwrite("animationManager", &Sprite::animationManager)
    ];


    luabind::module(state) [
        luabind::class_<AnimationManager>("AnimationManager")
            .def("Add", &AnimationManager::Add)
            .def("ChangeAnimation", &AnimationManager::ChangeAnimation)
    ];

    luabind::module(state) [
        luabind::class_<Input>("Input")
            .def("IsDown", &Input::IsDown)
            .def("IsPushed", &Input::IsPushed)
            .def("IsReleased", &Input::IsReleased)
            .enum_("KeyCode")
            [
                luabind::value("KEY_LEFT", 1),
                luabind::value("KEY_RIGHT", 2),
                luabind::value("KEY_UP", 3),
                luabind::value("KEY_DOWN", 4),
                luabind::value("KEY_A", 5),
                luabind::value("KEY_B", 6),
                luabind::value("KEY_X", 7),
                luabind::value("KEY_Y", 8),
                luabind::value("KEY_R", 9),
                luabind::value("KEY_L", 10),
                luabind::value("KEY_START", 11),
                luabind::value("KEY_SELECT", 12),
                luabind::value("KEY_ESCAPE", 13),
                luabind::value("KEY_DEBUG_1", 14),
                luabind::value("KEY_DEBUG_2", 15),
                luabind::value("KEY_DEBUG_3", 16),
                luabind::value("KEY_DEBUG_4", 17),
                luabind::value("LAST_KEY", 18)
            ]
    ];

    luabind::globals(state)["spriteManager"] = spriteManager;

    luaL_dofile(state, "load.lua");
    // /Lua ------------------
}

void Engine::Update()
{
    entityManager.Update();
    gfxEngine->Update();
}

void Engine::Draw()
{
    gfxEngine->Draw();
    gfxEngine->Flip();
}

void Engine::Run()
{
    while (!input.IsDown(Input::KEY_ESCAPE))
    {
        input.Handle();

        luabind::globals(state)["input"] = input;
        luaL_dofile(state, "run.lua");

        messageManager.ComputeAll();
        this->Update();
        this->Draw();
        Timer::Delay(10);
    }
    lua_close(state);
}
